﻿using System;

namespace K9Nano.Caching
{
    public interface ITypedCache<TCachedValue>: ITypedCacheCleaner where TCachedValue : class
    {
        /// <summary>
        /// Adds a value for the specified key to the cache.
        /// <para>
        /// The <c>Add</c> method will <b>not</b> be successful if the specified
        /// <paramref name="key"/> already exists within the cache!
        /// </para>
        /// </summary>
        bool Add(string key, TCachedValue value, TimeSpan? slidingTimeout = null, TimeSpan? absoluteTimeout = null);

        /// <summary>
        /// Puts a value for the specified key into the cache.
        /// <para>
        /// If the <paramref name="key"/> already exists within the cache, the existing value will
        /// be replaced with the new <paramref name="value"/>.
        /// </para>
        /// </summary>
        void Put(string key, TCachedValue value, TimeSpan? slidingTimeout = null, TimeSpan? absoluteTimeout = null);

        TCachedValue Update(string key, Func<TCachedValue, TCachedValue> updateValue);

        TCachedValue Get(string key);

        void Expire(string key, DateTimeOffset absoluteExpiration);

        void Expire(string key, TimeSpan slidingExpiration);
        
        bool Exists(string key);

        TCachedValue AddOrUpdate(string key, TCachedValue addValue, Func<TCachedValue, TCachedValue> updateValue, TimeSpan? slidingTimeout = null, TimeSpan? absoluteTimeout = null);

        TCachedValue GetOrAdd(string key, TCachedValue value, TimeSpan? slidingTimeout = null, TimeSpan? absoluteTimeout = null);

        TCachedValue GetOrAdd(string key, Func<string, TCachedValue> valueFactory, TimeSpan? slidingTimeout = null, TimeSpan? absoluteTimeout = null);

        bool TryGetOrAdd(string key, Func<string, TCachedValue> valueFactory, out TCachedValue value, TimeSpan? slidingTimeout = null, TimeSpan? absoluteTimeout = null);

        bool TryUpdate(string key, Func<TCachedValue, TCachedValue> updateValue, out TCachedValue value);
    }
}
